import { useMemo } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import {
  CartesianGrid,
  Legend,
  Line,
  LineChart,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from 'recharts';
import { useJobStore } from '@/models/job';
import type { JobWithValidation } from '@/models/job';
import type { TrainLogEvent, TrainLogMetricEntry } from '@/types/job';

interface TrainResultDynamicProps {
  job: JobWithValidation;
}

const palette = ['#2563eb', '#16a34a', '#f59e0b', '#ec4899', '#6366f1'];

const toNumberOrNull = (value: unknown): number | null => {
  if (value == null) return null;
  const numeric = Number(value);
  return Number.isFinite(numeric) ? numeric : null;
};

const formatFraction = (value: number | string | Array<number | string>): string => {
  const numeric = Array.isArray(value) ? Number(value[0]) : Number(value);
  return Number.isFinite(numeric) ? numeric.toFixed(4) : '—';
};

const formatPercent = (value: number | string | Array<number | string>): string => {
  const numeric = Array.isArray(value) ? Number(value[0]) : Number(value);
  return Number.isFinite(numeric) ? `${numeric.toFixed(2)}%` : '—';
};

function isMetricLog(log: TrainLogEvent): log is TrainLogMetricEntry {
  return log.type === 'metrics';
}

export default function TrainResultDynamic({ job }: TrainResultDynamicProps) {
  const logs = useJobStore((state) => state.logs);

  const metricLogs = useMemo(() => logs.filter(isMetricLog), [logs]);

  const {
    chartSeries,
    classAccuracySeries,
    classAccuracyKeys,
    availability,
  } = useMemo(() => {
    const chartSeries = metricLogs.map((entry, index) => ({
      step: entry.epoch ?? index,
      loss: toNumberOrNull(entry.loss),
      oa: toNumberOrNull(entry.oa),
      kappa: toNumberOrNull(entry.kappa),
      precision: toNumberOrNull(entry.precision),
      recall: toNumberOrNull(entry.recall),
    }));

    const keySet = new Set<string>();
    const classSeries = metricLogs.map((entry, index) => {
      const record: Record<string, number | null> = { step: entry.epoch ?? index };
      if (Array.isArray(entry.clsAcc)) {
        entry.clsAcc.forEach((value, idx) => {
          const label = `类别 ${idx + 1}`;
          keySet.add(label);
          const numeric = typeof value === 'number' ? value : Number(value);
          record[label] = Number.isFinite(numeric) ? numeric : null;
        });
      }
      return record;
    });

    const sortedKeys = Array.from(keySet).sort((a, b) => {
      const getIdx = (label: string) => Number(label.split(' ')[1] ?? 0);
      return getIdx(a) - getIdx(b);
    });

    const availability = {
      loss: chartSeries.some((item) => item.loss != null),
      oa: chartSeries.some((item) => item.oa != null),
      kappa: chartSeries.some((item) => item.kappa != null),
      precision: chartSeries.some((item) => item.precision != null),
      recall: chartSeries.some((item) => item.recall != null),
      classAccuracy:
        sortedKeys.length > 0 &&
        classSeries.some((entry) => sortedKeys.some((key) => entry[key] != null)),
    };

    return {
      chartSeries,
      classAccuracySeries: classSeries,
      classAccuracyKeys: sortedKeys,
      availability,
    };
  }, [metricLogs]);

  if (job.status !== 'running') {
    return null;
  }

  const hasMetrics = metricLogs.length > 0;

  return (
    <Card>
      <CardHeader>
        <CardTitle>实时训练指标</CardTitle>
      </CardHeader>
      <CardContent className="space-y-4">
        <Tabs defaultValue="loss" className="space-y-4">
          <TabsList className="flex-wrap justify-start gap-2 bg-muted/30 p-1">
            <TabsTrigger value="loss">Loss 曲线</TabsTrigger>
            {availability.oa && <TabsTrigger value="oa">OA</TabsTrigger>}
            {availability.kappa && <TabsTrigger value="kappa">Kappa</TabsTrigger>}
            {availability.precision && <TabsTrigger value="precision">Precision</TabsTrigger>}
            {availability.recall && <TabsTrigger value="recall">Recall</TabsTrigger>}
            {availability.classAccuracy && (
              <TabsTrigger value="class-accuracy">类别准确率</TabsTrigger>
            )}
          </TabsList>

          <TabsContent value="loss" className="mt-0 mb-0">
            {availability.loss ? (
              <ResponsiveContainer width="100%" height={300}>
                <LineChart
                  data={chartSeries}
                  margin={{ top: 16, right: 16, left: 12, bottom: 12 }}
                >
                  <CartesianGrid strokeDasharray="4 4" stroke="#e5e7eb" />
                  <XAxis dataKey="step" tickLine={false} axisLine={false} tickMargin={8} />
                  <YAxis tickLine={false} axisLine={false} tickMargin={4} />
                  <Tooltip cursor={{ strokeDasharray: '4 2' }} formatter={formatFraction} />
                  <Legend iconType="circle" verticalAlign="top" height={32} />
                  <Line
                    type="monotone"
                    dataKey="loss"
                    name="Loss"
                    stroke={palette[0]}
                    strokeWidth={2}
                    dot={false}
                    connectNulls
                    isAnimationActive={false}
                  />
                </LineChart>
              </ResponsiveContainer>
            ) : (
              <div className="rounded-lg border border-dashed border-border/60 p-6 text-sm text-muted-foreground">
                {hasMetrics ? '当前日志未包含 Loss 信息。' : '等待日志中的 Loss 数据...'}
              </div>
            )}
          </TabsContent>

          {availability.oa ? (
            <TabsContent value="oa" className="mt-0 mb-0">
              <ResponsiveContainer width="100%" height={300}>
                <LineChart data={chartSeries} margin={{ top: 16, right: 16, left: 12, bottom: 12 }}>
                  <CartesianGrid strokeDasharray="4 4" stroke="#e5e7eb" />
                  <XAxis dataKey="step" tickLine={false} axisLine={false} tickMargin={8} />
                  <YAxis tickLine={false} axisLine={false} tickMargin={4} domain={[0, 100]} />
                  <Tooltip cursor={{ strokeDasharray: '4 2' }} formatter={formatPercent} />
                  <Legend iconType="circle" verticalAlign="top" height={32} />
                  <Line
                    type="monotone"
                    dataKey="oa"
                    name="OA"
                    stroke={palette[1]}
                    strokeWidth={2}
                    dot={false}
                    connectNulls
                    isAnimationActive={false}
                  />
                </LineChart>
              </ResponsiveContainer>
            </TabsContent>
          ) : (
            <TabsContent value="oa" className="mt-0 mb-0">
              <div className="rounded-lg border border-dashed border-border/60 p-6 text-sm text-muted-foreground">
                {hasMetrics ? '当前日志未包含 OA 信息。' : '等待日志中的 OA 数据...'}
              </div>
            </TabsContent>
          )}

          {availability.kappa ? (
            <TabsContent value="kappa" className="mt-0 mb-0">
              <ResponsiveContainer width="100%" height={300}>
                <LineChart data={chartSeries} margin={{ top: 16, right: 16, left: 12, bottom: 12 }}>
                  <CartesianGrid strokeDasharray="4 4" stroke="#e5e7eb" />
                  <XAxis dataKey="step" tickLine={false} axisLine={false} tickMargin={8} />
                  <YAxis tickLine={false} axisLine={false} tickMargin={4} />
                  <Tooltip cursor={{ strokeDasharray: '4 2' }} formatter={formatFraction} />
                  <Legend iconType="circle" verticalAlign="top" height={32} />
                  <Line
                    type="monotone"
                    dataKey="kappa"
                    name="Kappa"
                    stroke={palette[2]}
                    strokeWidth={2}
                    dot={false}
                    connectNulls
                    isAnimationActive={false}
                  />
                </LineChart>
              </ResponsiveContainer>
            </TabsContent>
          ) : (
            <TabsContent value="kappa" className="mt-0 mb-0">
              <div className="rounded-lg border border-dashed border-border/60 p-6 text-sm text-muted-foreground">
                {hasMetrics ? '当前日志未包含 Kappa 信息。' : '等待日志中的 Kappa 数据...'}
              </div>
            </TabsContent>
          )}

          {availability.precision ? (
            <TabsContent value="precision" className="mt-0 mb-0">
              <ResponsiveContainer width="100%" height={300}>
                <LineChart data={chartSeries} margin={{ top: 16, right: 16, left: 12, bottom: 12 }}>
                  <CartesianGrid strokeDasharray="4 4" stroke="#e5e7eb" />
                  <XAxis dataKey="step" tickLine={false} axisLine={false} tickMargin={8} />
                  <YAxis tickLine={false} axisLine={false} tickMargin={4} />
                  <Tooltip cursor={{ strokeDasharray: '4 2' }} formatter={formatFraction} />
                  <Legend iconType="circle" verticalAlign="top" height={32} />
                  <Line
                    type="monotone"
                    dataKey="precision"
                    name="Precision"
                    stroke={palette[3]}
                    strokeWidth={2}
                    dot={false}
                    connectNulls
                    isAnimationActive={false}
                  />
                </LineChart>
              </ResponsiveContainer>
            </TabsContent>
          ) : (
            <TabsContent value="precision" className="mt-0 mb-0">
              <div className="rounded-lg border border-dashed border-border/60 p-6 text-sm text-muted-foreground">
                {hasMetrics ? '当前日志未包含 Precision 信息。' : '等待日志中的 Precision 数据...'}
              </div>
            </TabsContent>
          )}

          {availability.recall ? (
            <TabsContent value="recall" className="mt-0 mb-0">
              <ResponsiveContainer width="100%" height={300}>
                <LineChart data={chartSeries} margin={{ top: 16, right: 16, left: 12, bottom: 12 }}>
                  <CartesianGrid strokeDasharray="4 4" stroke="#e5e7eb" />
                  <XAxis dataKey="step" tickLine={false} axisLine={false} tickMargin={8} />
                  <YAxis tickLine={false} axisLine={false} tickMargin={4} />
                  <Tooltip cursor={{ strokeDasharray: '4 2' }} formatter={formatFraction} />
                  <Legend iconType="circle" verticalAlign="top" height={32} />
                  <Line
                    type="monotone"
                    dataKey="recall"
                    name="Recall"
                    stroke={palette[4]}
                    strokeWidth={2}
                    dot={false}
                    connectNulls
                    isAnimationActive={false}
                  />
                </LineChart>
              </ResponsiveContainer>
            </TabsContent>
          ) : (
            <TabsContent value="recall" className="mt-0 mb-0">
              <div className="rounded-lg border border-dashed border-border/60 p-6 text-sm text-muted-foreground">
                {hasMetrics ? '当前日志未包含 Recall 信息。' : '等待日志中的 Recall 数据...'}
              </div>
            </TabsContent>
          )}

          {availability.classAccuracy ? (
            <TabsContent value="class-accuracy" className="mt-0 mb-0">
              <ResponsiveContainer width="100%" height={300}>
                <LineChart
                  data={classAccuracySeries}
                  margin={{ top: 16, right: 16, left: 12, bottom: 12 }}
                >
                  <CartesianGrid strokeDasharray="4 4" stroke="#e5e7eb" />
                  <XAxis dataKey="step" tickLine={false} axisLine={false} tickMargin={8} />
                  <YAxis tickLine={false} axisLine={false} tickMargin={4} domain={[0, 100]} />
                  <Tooltip cursor={{ strokeDasharray: '4 2' }} formatter={formatPercent} />
                  <Legend iconType="circle" verticalAlign="top" height={32} />
                  {classAccuracyKeys.map((key, index) => (
                    <Line
                      key={key}
                      type="monotone"
                      dataKey={key}
                      name={key}
                      stroke={palette[index % palette.length]}
                      strokeWidth={2}
                      dot={false}
                      connectNulls
                      isAnimationActive={false}
                    />
                  ))}
                </LineChart>
              </ResponsiveContainer>
            </TabsContent>
          ) : (
            <TabsContent value="class-accuracy" className="mt-0 mb-0">
              <div className="rounded-lg border border-dashed border-border/60 p-6 text-sm text-muted-foreground">
                {hasMetrics ? '当前日志未包含类别准确率信息。' : '等待日志中的类别准确率数据...'}
              </div>
            </TabsContent>
          )}
        </Tabs>
      </CardContent>
    </Card>
  );
}
